#include "core/page/Page.hpp"
#include "common/MemCommon.hpp"
#include "util/Log.hpp"
#include "config/global_config.hpp"

Page::Page(std::fstream * file,FileHeader * fileHeader,PageHead * pageHead,std::vector<FieldInfo> *fieldList,std::vector<uint8_t> *page,std::vector<uint32_t> *slot) {
    this->mFile = file;
    this->mFileHeader = fileHeader;
    this->mPageHead = *pageHead;
    this->mFieldList = fieldList;
    this->mPage = page;
    this->mSlot = *slot;
}
Page::Page(Context &context,const std::string& name,uint32_t &pageNo){
    mFile = gTableConfig[name].file.get();
    mFileHeader = &gTableConfig[name].fileHeader;
    mFieldList = &gTableConfig[name].fieldInfo;
    //链表
    mPage = new std::vector<uint8_t>(PAGE_SIZE);
    int ret = FileCommon::readPage(*mFile,pageNo,*mPage);
    if(ret != 0){
        std::cerr << "IndexPage readPage error " << std::endl;
    }

    mPageHead = *new PageHead();
    ret = MemCommon::copyPageHeader(*mPage,mPageHead,PAGE_HEAD_SIZE);
    if(ret != 0){
        std::cerr << "IndexPage copyPageHeader is error " << std::endl;
    }
    mSlot = *new std::vector<uint32_t>(mPageHead.slotSize);
    memcpy(mSlot.data(),mPage->data() + PAGE_SIZE - (mPageHead.slotSize * sizeof(uint32_t)),mPageHead.slotSize * sizeof(uint32_t));

    mContext = &context;
}

int Page::updNextOffset(uint64_t newRecordOffset,uint64_t prevRecordOffset){
    if(prevRecordOffset == 0) return 0;
    std::vector<Cell> cells;
    CellCommon::vectorToCell(cells,*mPage,*mFieldList,mPage->data() + prevRecordOffset);
    cells.at(CELL_INDEX_NEXT).i64 = newRecordOffset;
    uint32_t size = 0;
    CellCommon::cellToVector(*mPage,cells,mPage->data() + prevRecordOffset,size);
    return 0;

};
int Page::updPrevOffset(uint64_t newRecordOffset,uint64_t nextRecordOffset){
    if(nextRecordOffset == 0) return 0;
    std::vector<Cell> cells;
    CellCommon::vectorToCell(cells,*mPage,*mFieldList,mPage->data() + nextRecordOffset);
    cells.at(CELL_INDEX_PREV).i64 = newRecordOffset;
    uint32_t size = 0;
    CellCommon::cellToVector(*mPage,cells,mPage->data() + nextRecordOffset,size);
    return 0;


};
size_t Page::vectorToCell(std::vector<Cell> &cells,uint8_t *beginMemoryAddress){
    cells.resize(mFieldList->size());
    size_t offset = 0;
    for (int i = 0; i < mFieldList->size(); ++i) {
        FieldInfo fieldInfo = mFieldList->at(i);
        Cell cell{};
        switch (fieldInfo.type) {
            case FieldType::INT:{
                cell.type = FieldType::INT;
                memcpy(&cell.i64,beginMemoryAddress + offset,INT_64_SIZE);
                offset += INT_64_SIZE;
                break;
            }
            case FieldType::STRING:{
                cell.type = FieldType::STRING;
                uint32_t size = 0;
                memcpy(&size,beginMemoryAddress + offset,INT_32_SIZE);
                offset += INT_32_SIZE;
                cell.str.resize(size);
                memcpy(cell.str.data(),beginMemoryAddress + offset,size);
                offset += size + 1;
                break;
            }
            case FieldType::DATETIME:{
                cell.type = FieldType::DATETIME;
                memcpy(&cell.datetime,beginMemoryAddress+offset,DATETIME_SIZE);
                offset += DATETIME_SIZE;
            }
        }
        cells.at(i) = cell;
    }
    return offset;
}
uint32_t Page::cellToVector(std::vector<Cell> &cells,uint8_t * beginMemoryAddress){
    uint32_t offset = 0;
    for (Cell cell:cells) {
        switch (cell.type) {
            case FieldType::INT:{
                memcpy(beginMemoryAddress + offset, &cell.i64, INT_64_SIZE);
                offset += INT_64_SIZE;
                break;
            }
            case FieldType::STRING:{
//                    const uint8_t* p = reinterpret_cast<const uint8_t*>(&cell.strlen);
                uint32_t len = static_cast<uint32_t>(cell.str.length());
                memcpy(beginMemoryAddress + offset,&len,INT_32_SIZE);
                offset += INT_32_SIZE;
                memcpy(beginMemoryAddress + offset,cell.str.data(),cell.str.length());
                offset += cell.str.length();
                const char * str = "\0";
                memcpy(beginMemoryAddress + offset,&str,1);
                offset+=1;
                break;
            }
            case FieldType::DATETIME:{
                memcpy(beginMemoryAddress + offset, &cell.datetime, DATETIME_SIZE);
                offset += DATETIME_SIZE;
                break;
            }
        }
    }
    return offset;
}

int Page::insert(std::vector<Cell> &cells) {
    int ret=0;
    uint32_t recordBeginOffset = mPageHead.freeOffset;
    mFileHeader->maxRecordNo++;
    mPageHead.recordCount++;
    cells.at(CELL_INDEX_NO).i64 = mFileHeader->maxRecordNo;
    uint32_t primaryIndex = CellCommon::findFieldPrimaryIndex(*mFieldList);
    uint64_t key = cells.at(primaryIndex).i64;
    cells.at(CELL_INDEX_OFFSET).i64 = recordBeginOffset;
    cells.at(CELL_INDEX_DELETED).i64 = UN_DELETED;
    if(key > mPageHead.maxRecordNo){
        uint32_t lastRecord =  mPageHead.lastRecord;
        mPageHead.maxRecordNo = key;
        cells.at(CELL_INDEX_NEXT).i64 = 0;
        cells.at(CELL_INDEX_PREV).i64 = lastRecord;
//        uint32_t offset = 0;
//        CellCommon::cellToVector(*page,cells,page->data() + recordBeginOffset,offset);

//        cellToVector(cells,page->data() + recordBeginOffset);
        if(recordBeginOffset == PAGE_HEAD_SIZE){
            mPageHead.firstRecord = recordBeginOffset;
        }else{
            updNextOffset(recordBeginOffset,lastRecord);
        };
        // 更新最后一条数据偏移量
        mPageHead.lastRecord = recordBeginOffset;
        mPageHead.maxRecordNo = key;

        mSlot.push_back(recordBeginOffset);

    }else{
        // 通过二分法查询寻需要插入的位置
        auto [found, pos] = findRecordIndex(key);
        // right偏移量
        uint32_t rightOffset = mSlot.at(pos);
        std::vector<Cell> rightCells;
        vectorToCell(rightCells,mPage->data()+rightOffset);
        //修改next = right
        cells.at(CELL_INDEX_NEXT).i64 = rightOffset;
        // 修改prev = rihgt的prev
        cells.at(CELL_INDEX_PREV).i64 = rightCells.at(CELL_INDEX_PREV).i64;
        // 修改right记录的prev等于自己
        rightCells.at(CELL_INDEX_PREV).i64 = recordBeginOffset;
        // 保存right
        cellToVector(rightCells,mPage->data()+rightOffset);
        // 更新left 的next指向自己
        if(cells.at(CELL_INDEX_PREV).i64 == 0){
            mPageHead.firstRecord = recordBeginOffset;
        }else{
            updNextOffset(recordBeginOffset,cells.at(CELL_INDEX_PREV).i64);
        }

        // 插入数据
        mSlot.insert(mSlot.begin() + pos,recordBeginOffset);
    }


    uint32_t rowSize = cellToVector(cells,mPage->data() + recordBeginOffset);
    // 更新空闲区指针
    mPageHead.freeOffset +=rowSize;
    // 更新空闲指针偏移量
    mPageHead.freeSize -= rowSize;
    // 更新slot
    mPageHead.slotSize = mSlot.size();
    // 保存slot
    uint32_t slotLen = mPageHead.slotSize * sizeof(uint32_t);
    memcpy(mPage->data() + PAGE_SIZE - slotLen, mSlot.data(), slotLen);
    // 更新 page header
    memcpy(mPage->data(), &mPageHead, PAGE_HEAD_SIZE);

    Log::log(mPageHead);
//    Log::log(slot);
    Log::log(cells,*mFieldList);
    ret = FileCommon::writePage(*mFile,mPageHead.pageNo,*mPage);
    if(ret != 0){
        std::cerr << "writePage create record error " << std::endl;
    }
    // 更新file header

    FileCommon::saveFileHeader(*mFile,*mFileHeader);
    return ret;
}



int Page::createPage() {
//    std::vector<uint8_t> page(PAGE_SIZE);
    mFileHeader->lastPage ++;
    mFileHeader->pageCount++;
    mFileHeader->rootIndexPageNo = mFileHeader->lastPage;
    mPageHead.pageNo = mFileHeader->lastPage;
    mPageHead.pageNext = 0;
    mPageHead.pagePrev = 0;
    mPageHead.recordCount = 0;
    mPageHead.maxTrxId = 0;
    mPageHead.firstRecord = PAGE_HEAD_SIZE;
    mPageHead.freeOffset = PAGE_HEAD_SIZE;
    mPageHead.freeSize = PAGE_SIZE - PAGE_HEAD_SIZE;
    mPageHead.slotSize = 0;
    mPageHead.pageType = PageType::DATA;
    mPageHead.maxRecordNo = 0;
    mPageHead.lastRecord = 0;
    memcpy(mPage->data(),&mPageHead,PAGE_HEAD_SIZE);
    return 0;
}
int Page::readPageAll(uint32_t offset){
    std::vector<Cell> cells;
    CellCommon::vectorToCell(cells,*mPage,*mFieldList,mPage->data() + offset);
    if(cells.empty()){
        return 0;
    }
    if(cells[CELL_INDEX_DELETED].i64 == UN_DELETED){
        mPageData.push_back(cells);
    }
//    Log::log(cells,*fieldList,"xx");
    if(cells.at(CELL_INDEX_NEXT).i64 != 0){
        readPageAll(cells.at(CELL_INDEX_NEXT).i64);
    }
    return 0;
}
uint32_t Page::findKey(uint32_t mid)const{
    if(mPageHead.pageType == PageType::DATA){
        std::vector<Cell> cellRow;
        CellCommon::vectorToCell(cellRow, *mPage, *mFieldList, mPage->data() + mSlot.at(mid));
        uint32_t index = CellCommon::findFieldPrimaryIndex(*mFieldList);
        return cellRow.at(index).i64;
    }else if(mPageHead.pageType == PageType::INDEX){
        IndexRecord indexRecord{};
        memcpy(&indexRecord,mPage->data()+mSlot.at(mid),sizeof(uint32_t) );
        return indexRecord.key;
    }else{
        std::cout << " isEmp pageType " << (int) mPageHead.pageType << std::endl;
        return 0;
    }
}

// 这个方法会找到当前key的后一个key的下标。 假设[1,3,5,7,8]  newKey = 4 那么返回5， 如果newKey = 2 返回3
std::pair<bool, uint32_t> Page::findRecordIndex(uint32_t newKey) const {
    if (mSlot.empty()) {
        return {true, 0}; // 空数组时插入位置为0
    }

    uint32_t low = 0;
    uint32_t high = mSlot.size() - 1;

    while (low <= high) {
        uint32_t mid = low + (high - low) / 2;  // 避免溢出
        uint32_t key = findKey(mid);

        if (newKey < key) {
            if (mid == 0) break;  // 防止无符号数下溢
            high = mid - 1;
        } else if (newKey > key) {
            low = mid + 1;
        } else {
            // 找到相同主键，返回false + 槽位索引
            std::cout << "命中主键索引id " << newKey << std::endl;
            return {false, mid};
        }
    }
//    insert 4
//    [1,2,3,5,6,9]
//    mid = 2
//    l = 0 h = 5
//
//    l = 3 h = 5 mid 4
//
//    l = 3 h = 3 mid 3
//
//    l = 3 h = 2 mid 2


    // 没找到相同的，返回应该插入的位置
    return {true, low};


}

int Page::updRecordDeleted(uint32_t offset) {
    std::vector<Cell> cell;
    vectorToCell(cell,mPage->data()+ offset);
    return updRecordDeleted(cell);
}

int Page::updRecordDeleted(std::vector<Cell> &cell) {
    cell[CELL_INDEX_DELETED].i64 = 1;
    cellToVector(cell,mPage->data() + cell[CELL_INDEX_OFFSET].i64);
    return 0;
}

int Page::updRecordAll(std::vector<UpdateSetItem> &updateSets) {
//    for (std::vector<Cell> cell: mPageData) {
//        std::vector<Cell> newCell = cell;
//        newCell[CELL_INDEX_TRANSACTION].i64 = mContext->trx->trxId;
//        newCell[CELL_INDEX_UNDO_LOG_OFFSET].i64 = offset;
//        newCell[CELL_INDEX_DELETED].i64 = DELETED;
//
//
//        for (UpdateSetItem updateSetItem: updateSets) {
//            newCell[updateSetItem.colIndex] = updateSetItem.value;
//        }
//
//    }
return 0;
}

int Page::saveAll(){
    int ret = FileCommon::writePage(*mFile,mPageHead.pageNo,*mPage);
    if(ret != 0){
        std::cerr << "saveAll writePage error " << std::endl;
        return ret;
    }

    ret = FileCommon::saveFileHeader(*mFile,*mFileHeader);
    if(ret != 0){
        std::cerr << "saveAll saveFileHeader error " << std::endl;
        return ret;
    }
    return ret;
};